package com.zonski.jbots.game.entity;

import com.zonski.jbots.engine.*;
import com.zonski.jbots.engine.entity.AbstractMind;
import com.zonski.jbots.engine.entity.MovingEntity;
import com.zonski.jbots.engine.entity.Mind;

import com.zonski.jbots.game.JBotsConstants;
import com.zonski.jbots.game.EntityHelper;

public class MinimalInputMind extends AbstractMind
{
    public static final int NORTH = 0;
    public static final int SOUTH = 1;
    public static final int EAST  = 2;
    public static final int WEST  = 3;
    public static final int BOMB  = 4;
    public static final int COMET = 5;
    public static final int EGG   = 6;

    public static final int MAX_DEFINED_INPUTS = 7;

    private static final int CONCIEVED_SPEED = 100;

    private boolean[] down;
    private boolean[] readAtLeastOnce;

    public MinimalInputMind()
    {
        this(MAX_DEFINED_INPUTS);
    }
        

    public MinimalInputMind(int maxInputs)
    {
        this.down = new boolean[maxInputs];
        this.readAtLeastOnce = new boolean[maxInputs];
        for(int i=0; i<maxInputs; i++)
        {
            readAtLeastOnce[i] = true;
        }
    }

    public boolean isDown(int inputId)
    {
        boolean b = down[inputId] || !readAtLeastOnce[inputId];
        readAtLeastOnce[inputId] = true;
        return b;
    }

    public void setDown(int inputId, boolean inputDown)
    {
        down[inputId] = inputDown;
        if(inputDown)
        {
            readAtLeastOnce[inputId] = false;
        }
    }

    public void update(Engine engine)
        throws Exception
    {
        if(this.getEntity().getMode() == Modes.DEAD)
        {
            this.getEntity().setRemovable(true);
            this.getEntity().getDevice().play("DeadBot", 1);
            // put down some goodies
            Entity capacity = EntityHelper.addEntity(JBotsConstants.CAPACITY, this.getEntity(), engine, 0);
            EntityHelper.centreAtClosestTile(
                    capacity.bounds, this.getEntity().bounds, engine.getRoom()
            );
            capacity.setMaxCharge(this.getEntity().getMaxCharge()/2);

            return;
        }
        int direction = this.getEntity().direction;
        int speed = 0;

        boolean n = isDown(NORTH);
        boolean s = isDown(SOUTH);
        boolean e = isDown(EAST);
        boolean w = isDown(WEST);
        boolean bomb = isDown(BOMB);
        boolean comet = isDown(COMET);
        boolean egg = isDown(EGG);

        Rectangle bounds = this.getEntity().bounds;
        int cx = bounds.getCentreX();
        int cy = bounds.getCentreY();
        int tileSize = engine.getRoom().getTileSize();

        if(w)
        {
            int off = (cy + tileSize/2) % tileSize;
            if(off != 0)
            {
                // align with the closest tile
                if(off > tileSize/2)
                {
                    // move down by the difference
                    direction = Directions.NORTH;
                    speed = tileSize - off;
                }else{
                    //move up by the difference
                    direction = Directions.SOUTH;
                    speed = off;
                }
            }else{
                speed = CONCIEVED_SPEED;
                direction = Directions.WEST;
            }
        }
        else if(e)
        {
            int off = (cy + tileSize/2) % tileSize;
            if(off != 0)
            {
                // align with the closest tile
                if(off > tileSize/2)
                {
                    // move down by the difference
                    direction = Directions.NORTH;
                    speed = tileSize - off;
                }else{
                    //move up by the difference
                    direction = Directions.SOUTH;
                    speed = off;
                }
            }else{
                speed = CONCIEVED_SPEED;
                direction = Directions.EAST;
            }
        }
        else if(n)
        {
            int off = (cx + tileSize/2) % tileSize;
            if(off != 0)
            {
                // align with the closest tile
                if(off > tileSize/2)
                {
                    // move down by the difference
                    direction = Directions.EAST;
                    speed = tileSize - off;
                }else{
                    //move up by the difference
                    direction = Directions.WEST;
                    speed = off;
                }
            }else{
                speed = CONCIEVED_SPEED;
                direction = Directions.NORTH;
            }
        }
        else if(s)
        {
            int off = (cx + tileSize/2) % tileSize;
            if(off != 0)
            {
                // align with the closest tile
                if(off > tileSize/2)
                {
                    // move down by the difference
                    direction = Directions.EAST;
                    speed = tileSize - off;
                }else{
                    //move up by the difference
                    direction = Directions.WEST;
                    speed = off;
                }
            }else{
                speed = CONCIEVED_SPEED;
                direction = Directions.SOUTH;
            }
        }
        MovingEntity movingEntity = (MovingEntity)this.getEntity();
        // TODO : we don't really use x and y
        movingEntity.setTargetVelocity(speed);
        movingEntity.setTargetDirection(direction);
        if(speed != 0)
        {
            movingEntity.setMode(Modes.WALKING);
        }else{
            movingEntity.setMode(Modes.NONE);
        }
        UsableResource resource = (UsableResource)movingEntity.getResource(
                JBotsConstants.BOMB);
        if(resource != null)
        {
            if(bomb)
            {
                resource.startUsing(direction);
            }else{
                resource.stopUsing();
            }
        }
        resource = (UsableResource)movingEntity.getResource(
                JBotsConstants.COMET);
        if(resource != null)
        {
            if(comet)
            {
                resource.startUsing(direction);
            }else{
                resource.stopUsing();
            }
        }
        resource = (UsableResource)movingEntity.getResource(
                JBotsConstants.EGG);
        if(resource != null)
        {
            if(egg)
            {
                resource.startUsing(direction);
            }else{
                resource.stopUsing();
            }
        }
    }

    public Mind copy()
    {
        return new MinimalInputMind();
    }
}
